﻿using System.ComponentModel.Composition;
using System.Reflection;
using Cubicle.Core.Interfaces;

namespace Cubicle.Core.Processors.Invoke
{
    [Export("Cubicle.Processors.Invoke.InvokeProcessor", typeof(IProcessor<InstructionRequest>))]
    [ExportMetadata("Name", "InvokeProcessor")]
    [ExportMetadata("Description", "Invokes the identified target method")]
    public class InvokeProcessor : InstructionRequestProcessor
    {

        #region Overrides of Processor<InstructionRequest>

        public InvokeProcessor() : base(RequestType.AllMethod) { }

        public override InstructionRequest ConditionalProcess(InstructionRequest request)
        {
            if (request.TargetMethod == null)
            {
                request.Fail("No method to invoke.");
                return request;
            }
            // Before execute event
            var eventArgs = new InstructionEventArgs(InstructionEventType.BeforeInvoke, request);
            RaiseProcessorEvent(this, eventArgs);

            var result = request.TargetMethod.Invoke(request.Target, BindingFlags.InvokeMethod, null, request.Parameters, null);

            // After execute event
            eventArgs = new InstructionEventArgs(InstructionEventType.AfterInvoke, request);
            RaiseProcessorEvent(this, eventArgs);
            
            request.Complete(result);
            return request;
        }

        #endregion
    }
}